package top.lishuoboy.hutool.crypto;

import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.log.StaticLog;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.KeyPair;

/**
 * @author ：lishuoboy
 * @date ：Created in 2020-11-6 14:20
 * @description：
 * @modified By：
 * @version: $
 */
public class SecureUtilTest {

    public static void main(String[] args) throws Exception {
//        digesterTest();
//        symmetricCryptoTest();
//        AsymmetricCryptoTest();
        sm3();

    }


    /**
     * 摘要算法 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512
     */
    private static void digesterTest() throws Exception {
        String pass = "1";
        StaticLog.debug("明文=={}", pass);

        // 1、各种摘要算法
        StaticLog.debug("密文 MD2=={}", new Digester(DigestAlgorithm.MD2).digestHex(pass));

        StaticLog.debug("密文 MD5=={}", new Digester(DigestAlgorithm.MD5).digestHex(pass));
        StaticLog.debug("密文 MD5=={}", DigestUtil.md5Hex(pass));
        StaticLog.debug("密文 MD5=={}", SecureUtil.md5(pass));
        StaticLog.debug("密文 MD5=={}", SecureUtil.md5().digestHex(pass));

        StaticLog.debug("密文 SHA1=={}", new Digester(DigestAlgorithm.SHA1).digestHex(pass));
        StaticLog.debug("密文 SHA1=={}", DigestUtil.sha1Hex(pass));
        StaticLog.debug("密文 SHA1=={}", SecureUtil.sha1(pass));
        StaticLog.debug("密文 SHA1=={}", SecureUtil.sha1().digestHex(pass));

        StaticLog.debug("密文 SHA256=={}", new Digester(DigestAlgorithm.SHA256).digestHex(pass));
        StaticLog.debug("密文 SHA256=={}", DigestUtil.sha256Hex(pass));
        StaticLog.debug("密文 SHA256=={}", SecureUtil.sha256(pass));
        StaticLog.debug("密文 SHA256=={}", SecureUtil.sha256().digestHex(pass));

        StaticLog.debug("密文 SHA384=={}", new Digester(DigestAlgorithm.SHA384).digestHex(pass));

        StaticLog.debug("密文 SHA512=={}", new Digester(DigestAlgorithm.SHA512).digestHex(pass));

        // 2、给字符串、文件生成MD5摘要
        // 2.1 字符串
        StaticLog.debug("字符串 MD5=={}", new Digester(DigestAlgorithm.MD5).digestHex(pass));
        StaticLog.debug("字符串 MD5=={}", DigestUtil.md5Hex(pass));
        StaticLog.debug("字符串 MD5=={}", SecureUtil.md5(pass));
        // 2.2 文件
        File file = FileUtil.file(new File("").getCanonicalPath(), "/tmp/captcha.png");
        StaticLog.debug("文件 MD5=={}", new Digester(DigestAlgorithm.MD5).digestHex(file));
        StaticLog.debug("文件 MD5=={}", DigestUtil.md5Hex(file));
        StaticLog.debug("文件 MD5=={}", SecureUtil.md5(file));

        // 2.3 文件流
        InputStream fis = new FileInputStream(file);
        StaticLog.debug("文件流 MD5=={}", new Digester(DigestAlgorithm.MD5).digestHex(fis));
//        fis.close();
        fis = new FileInputStream(file);
        StaticLog.debug("文件流 MD5=={}", DigestUtil.md5Hex(fis));
        fis = new FileInputStream(file);
        StaticLog.debug("文件流 MD5=={}", SecureUtil.md5(fis));


    }

    /**
     * 对称加密 AES、ARCFOUR、Blowfish、DES、DESede、RC2、PBEWithMD5AndDES、PBEWithSHA1AndDESede、PBEWithSHA1AndRC2_40
     */
    private static void symmetricCryptoTest() throws FileNotFoundException {
        String pass = "1";

        byte[] key;
        // 自定义 key
        byte[] myKey = "lishuoboy".getBytes();
        SymmetricCrypto crypto;

        // 1、各种对称加密算法
        // 随机生成密钥
        key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
        //构建
        crypto = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
        //加密为16进制表示
        StaticLog.debug("AES 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("AES 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));
        StaticLog.debug("AES 加密=={}", SecureUtil.aes(key).encryptHex(pass));
        StaticLog.debug("AES 解密=={}", SecureUtil.aes(key).decryptStr(SecureUtil.aes(key).encryptHex(pass)));

        key = SecureUtil.generateKey(SymmetricAlgorithm.ARCFOUR.getValue()).getEncoded();
        crypto = new SymmetricCrypto(SymmetricAlgorithm.ARCFOUR, key);
        StaticLog.debug("ARCFOUR 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("ARCFOUR 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));

        key = SecureUtil.generateKey(SymmetricAlgorithm.Blowfish.getValue()).getEncoded();
        crypto = new SymmetricCrypto(SymmetricAlgorithm.Blowfish, myKey);
        StaticLog.debug("Blowfish 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("Blowfish 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));

        key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue()).getEncoded();
        crypto = new SymmetricCrypto(SymmetricAlgorithm.DES, myKey);
        StaticLog.debug("DES 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("DES 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));
        StaticLog.debug("DES 加密=={}", SecureUtil.des(key).encryptHex(pass));
        StaticLog.debug("DES 解密=={}", SecureUtil.des(key).decryptStr(SecureUtil.des(key).encryptHex(pass)));

        key = SecureUtil.generateKey(SymmetricAlgorithm.DESede.getValue()).getEncoded();
        crypto = new SymmetricCrypto(SymmetricAlgorithm.DESede, key);
        StaticLog.debug("DESede 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("DESede 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));
        StaticLog.debug("DESede 加密=={}", SecureUtil.desede(key).encryptHex(pass));
        StaticLog.debug("DESede 解密=={}", SecureUtil.desede(key).decryptStr(SecureUtil.desede(key).encryptHex(pass)));

        key = SecureUtil.generateKey(SymmetricAlgorithm.RC2.getValue()).getEncoded();
        crypto = new SymmetricCrypto(SymmetricAlgorithm.RC2, myKey);
        StaticLog.debug("RC2 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("RC2 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));

        crypto = new SymmetricCrypto(SymmetricAlgorithm.PBEWithMD5AndDES, myKey);
        StaticLog.debug("PBEWithMD5AndDES 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("PBEWithMD5AndDES 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));

        crypto = new SymmetricCrypto(SymmetricAlgorithm.PBEWithSHA1AndDESede, myKey);
        StaticLog.debug("PBEWithSHA1AndDESede 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("PBEWithSHA1AndDESede 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));

        crypto = new SymmetricCrypto(SymmetricAlgorithm.PBEWithSHA1AndRC2_40, myKey);
        StaticLog.debug("PBEWithSHA1AndRC2_40 加密=={}", crypto.encryptHex(pass));
        StaticLog.debug("PBEWithSHA1AndRC2_40 解密=={}", crypto.decryptStr(crypto.encryptHex(pass)));

    }


    /**
     * 非对称加密 RSA、DSA
     */
    private static void AsymmetricCryptoTest() {
        String pass = "1";
        StaticLog.debug("明文=={}", pass);

        String asymmetricAlgorithm = AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue();

        // 生成密钥对
        KeyPair pair = SecureUtil.generateKeyPair(asymmetricAlgorithm);

//        String privateKey = Base64.encode(pair.getPrivate().getEncoded());
//        String publicKey = Base64.encode(pair.getPublic().getEncoded());
        String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJLus1455EFCSerkWPUEqKNhxC0bUiamDS24AH154iYNT0yAgVqY1VgOzj3/X4kv18iHkdB7QumrDmgAZ1nfQzzE1p0eOYGNEOlVJCNUcZEy5Teo69PK1Aa76MJQmbZFyzsTS/2eo4ukgXBm6aICvGE5oiktOEtvKvOzQ7/uQhVTAgMBAAECgYEAjvpChrV03OABh9Yujja7V0lCmdYVKdC50DxWFcOuAfM/sCT4Os2wBSFbJk9Div6ITvVFOgdIBJPUz/VcnMK57IOVGPM+1BLvOHcbPPGgVNzJR/rM8dHB0ifJuvEwn15tAjPu4rSD6rxAzq7uwz9RLkpMfo6lVgnA+RMWjaBTz/ECQQDY+RNLyF3004ounFxWesu+9Bbe1SYXwK8qcDMk2vg8HxZMbyBEPq+PaVdx627EL9v0YjJXhlE08PhqKnCmwsj5AkEArVx6fYN7mpIhdl/wl5Z1sYs4NUj8iU0Czh9dLYmE8nTimSsXcQgjSEHm6qNyEBUXLp9Z4al/I3UrDwnWAGlPqwJBAKikuH3PyE+yWJYwDIlfOpw6ZshejhQqPTxUJzx/QjCgzRktyrugqZ5jd4dhQiAVPvZtmMl06gunPL5wLE1B2ykCQE6qCgLuKKYo7Poz6o4+fcVEcQrsxXrf8Qfq/3LsVeFW3IO4I/jsQmZFUSzjYZyelVhYgoZ9TO2f+xvl0K97GeUCQDE5A0wBTKIVdBY6IzGvzVYOm1fpLFuuiITtsJB5NBQixLVEBJSlIb5WHXDSGRMrh6vhIIbb0WZBaIviN02iJeU=";
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCS7rNeOeRBQknq5Fj1BKijYcQtG1Impg0tuAB9eeImDU9MgIFamNVYDs49/1+JL9fIh5HQe0Lpqw5oAGdZ30M8xNadHjmBjRDpVSQjVHGRMuU3qOvTytQGu+jCUJm2Rcs7E0v9nqOLpIFwZumiArxhOaIpLThLbyrzs0O/7kIVUwIDAQAB";
        StaticLog.debug("privateKey=={}", privateKey);
        StaticLog.debug("publicKey=={}", publicKey);

        RSA rsa = new RSA(asymmetricAlgorithm, privateKey, publicKey);
        String encrypt = rsa.encryptHex(pass.getBytes(), KeyType.PrivateKey);
        StaticLog.debug("RSA 加密=={}", encrypt);
        String decrypt = rsa.decryptStr(encrypt, KeyType.PublicKey);
        StaticLog.debug("RSA 解密=={}", decrypt);


    }

    /**
     * 国密-非对称加密算法 SM2
     */
    private static void sm2() {
        //略
    }

    /**
     * 国密-摘要算法 SM3
     */
    private static void sm3() {
        String pass = "1";
        StaticLog.debug("明文=={}", pass);

        String digestHex = SmUtil.sm3(pass);
        StaticLog.debug("密文 SM2=={}", digestHex);
    }

    /**
     * 国密-对称加密算法 SM4
     */
    private static void sm4() {
        //略
    }


}
